import java.util.List;
import java.util.Map;

public class CodeGenerator {
    private String basePackage;
    private String className;
    private String lowerClassName;
    private String tableName;
    private List<Map<String, String>> attributes;
    private boolean useLombok;
    private boolean useSwagger;
    private boolean useMyBatisPlus;
    
    public CodeGenerator(String basePackage, String className, String lowerClassName, String tableName, 
                         List<Map<String, String>> attributes, boolean useLombok, 
                         boolean useSwagger, boolean useMyBatisPlus) {
        this.basePackage = basePackage;
        this.className = className;
        this.lowerClassName = lowerClassName;
        this.tableName = tableName;
        this.attributes = attributes;
        this.useLombok = useLombok;
        this.useSwagger = useSwagger;
        this.useMyBatisPlus = useMyBatisPlus;
    }
    
    // 生成实体类
    public String generateEntity() {
        StringBuilder code = new StringBuilder();
        code.append("package ").append(basePackage).append(".entity;\n\n");
        
        // 添加必要的导入
        code.append("import java.io.Serializable;\n");
        if (useLombok) {
            code.append("import lombok.Data;\n");
            if (useMyBatisPlus) {
                code.append("import com.baomidou.mybatisplus.annotation.TableName;\n");
            }
        } else {
            code.append("import java.util.Date;\n");
        }
        
        // 添加Swagger注解
        if (useSwagger) {
            code.append("import io.swagger.annotations.ApiModel;\n");
            code.append("import io.swagger.annotations.ApiModelProperty;\n");
        }
        
        code.append("\n");
        
        // 类注解
        if (useLombok) {
            code.append("@Data\n");
        }
        if (useSwagger) {
            code.append("@ApiModel(value = \"").append(className).append("\", description = \"").append(className).append(" entity\")\n");
        }
        if (useMyBatisPlus) {
            code.append("@TableName(\"").append(tableName).append("\")\n");
        }
        
        // 类定义
        code.append("public class ").append(className).append(" implements Serializable {\n");
        code.append("    private static final long serialVersionUID = 1L;\n\n");
        
        // 生成属性
        for (Map<String, String> attr : attributes) {
            String name = attr.get("name");
            String type = attr.get("type");
            String comment = attr.get("comment");
            
            // 添加注释
            if (useSwagger && !comment.isEmpty()) {
                code.append("    @ApiModelProperty(value = \"").append(comment).append("\")\n");
            }
            
            // 添加属性
            code.append("    private ").append(type).append(" ").append(name).append(";\n\n");
        }
        
        // 如果不使用Lombok，生成getter/setter
        if (!useLombok) {
            generateGettersSetters(code);
        }
        
        code.append("}");
        return code.toString();
    }
    
    // 生成Mapper接口
    public String generateMapper() {
        StringBuilder code = new StringBuilder();
        code.append("package ").append(basePackage).append(".mapper;\n\n");
        
        code.append("import ").append(basePackage).append(".entity.").append(className).append(";\n");
        if (useMyBatisPlus) {
            code.append("import com.baomidou.mybatisplus.core.mapper.BaseMapper;\n\n");
            code.append("public interface ").append(className).append("Mapper extends BaseMapper<").append(className).append("> {\n");
        } else {
            code.append("import org.apache.ibatis.annotations.Mapper;\n\n");
            code.append("@Mapper\n");
            code.append("public interface ").append(className).append("Mapper {\n\n");
            
            // 生成基本的CRUD方法
            generateBasicCrudMethods(code);
        }
        
        code.append("}");
        return code.toString();
    }
    
    // 生成Service接口
    public String generateServiceInterface() {
        StringBuilder code = new StringBuilder();
        code.append("package ").append(basePackage).append(".service;\n\n");
        
        code.append("import ").append(basePackage).append(".entity.").append(className).append(";\n");
        if (useMyBatisPlus) {
            code.append("import com.baomidou.mybatisplus.extension.service.IService;\n\n");
            code.append("public interface I").append(className).append("Service extends IService<").append(className).append("> {\n");
        } else {
            code.append("import java.util.List;\n\n");
            code.append("public interface I").append(className).append("Service {\n\n");
            
            // 生成基本的Service方法
            generateBasicServiceMethods(code);
        }
        
        code.append("}");
        return code.toString();
    }
    
    // 生成Service实现类
    public String generateServiceImpl() {
        StringBuilder code = new StringBuilder();
        code.append("package ").append(basePackage).append(".service.impl;\n\n");
        
        code.append("import ").append(basePackage).append(".entity.").append(className).append(";\n");
        code.append("import ").append(basePackage).append(".mapper.").append(className).append("Mapper;\n");
        code.append("import ").append(basePackage).append(".service.I").append(className).append("Service;\n");
        
        if (useMyBatisPlus) {
            code.append("import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;\n");
        } else {
            code.append("import org.springframework.beans.factory.annotation.Autowired;\n");
            code.append("import org.springframework.stereotype.Service;\n");
            code.append("import java.util.List;\n");
        }
        
        code.append("\n");
        
        if (useMyBatisPlus) {
            code.append("@Service\n");
            code.append("public class ").append(className).append("ServiceImpl extends ServiceImpl<").append(className).append("Mapper, ").append(className).append("> implements I").append(className).append("Service {\n");
        } else {
            code.append("@Service\n");
            code.append("public class ").append(className).append("ServiceImpl implements I").append(className).append("Service {\n\n");
            
            code.append("    @Autowired\n");
            code.append("    private ").append(className).append("Mapper ").append(lowerClassName).append("Mapper;\n\n");
            
            // 实现Service方法
            generateServiceMethodImplementations(code);
        }
        
        code.append("}");
        return code.toString();
    }
    
    // 生成Controller
    public String generateController() {
        StringBuilder code = new StringBuilder();
        code.append("package ").append(basePackage).append(".controller;\n\n");
        
        code.append("import ").append(basePackage).append(".entity.").append(className).append(";\n");
        code.append("import ").append(basePackage).append(".service.I").append(className).append("Service;\n");
        
        code.append("import org.springframework.web.bind.annotation.*;\n");
        code.append("import org.springframework.beans.factory.annotation.Autowired;\n");
        code.append("import org.springframework.http.ResponseEntity;\n");
        
        if (useSwagger) {
            code.append("import io.swagger.annotations.Api;\n");
            code.append("import io.swagger.annotations.ApiOperation;\n");
        }
        
        code.append("import java.util.List;\n\n");
        
        if (useSwagger) {
            code.append("@Api(tags = \"").append(className).append(" Management\")\n");
        }
        code.append("@RestController\n");
        code.append("@RequestMapping(\"/").append(lowerClassName).append("\")\n");
        code.append("public class ").append(className).append("Controller {\n\n");
        
        code.append("    @Autowired\n");
        code.append("    private I").append(className).append("Service ").append(lowerClassName).append("Service;\n\n");
        
        // 生成Controller方法
        generateControllerMethods(code);
        
        code.append("}");
        return code.toString();
    }
    
    // 生成MyBatis XML映射文件
    public String generateMyBatisXml() {
        StringBuilder code = new StringBuilder();
        code.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        code.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
        code.append("<mapper namespace=\"").append(basePackage).append(".mapper.").append(className).append("Mapper\">\n\n");
        
        // 生成resultMap
        code.append("    <resultMap id=\"BaseResultMap\" type=\"").append(basePackage).append(".entity.").append(className).append("\">\n");
        
        for (Map<String, String> attr : attributes) {
            String name = attr.get("name");
            String column = toUnderScoreCase(name);
            
            code.append("        <result column=\"").append(column).append("\" property=\"").append(name).append("\" />\n");
        }
        
        code.append("    </resultMap>\n\n");
        
        // 如果不使用MyBatis-Plus，生成基本SQL语句
        if (!useMyBatisPlus) {
            generateBasicSqlStatements(code);
        }
        
        code.append("</mapper>");
        return code.toString();
    }
    
    // 生成基本的CRUD方法
    private void generateBasicCrudMethods(StringBuilder code) {
        code.append("    /**\n");
        code.append("     * Query ").append(className).append(" list\n");
        code.append("     */\n");
        code.append("    List<").append(className).append("> select").append(className).append("List(").append(className).append(" ").append(lowerClassName).append(");\n\n");
        
        code.append("    /**\n");
        code.append("     * Query ").append(className).append(" details\n");
        code.append("     */\n");
        code.append("    ").append(className).append(" select").append(className).append("ById(Long id);\n\n");
        
        code.append("    /**\n");
        code.append("     * Add ").append(className).append("\n");
        code.append("     */\n");
        code.append("    int insert").append(className).append("(").append(className).append(" ").append(lowerClassName).append(");\n\n");
        
        code.append("    /**\n");
        code.append("     * Update ").append(className).append("\n");
        code.append("     */\n");
        code.append("    int update").append(className).append("(").append(className).append(" ").append(lowerClassName).append(");\n\n");
        
        code.append("    /**\n");
        code.append("     * Delete ").append(className).append("\n");
        code.append("     */\n");
        code.append("    int delete").append(className).append("ById(Long id);\n\n");
    }
    
    // 生成基本的Service方法
    private void generateBasicServiceMethods(StringBuilder code) {
        code.append("    /**\n");
        code.append("     * Query ").append(className).append(" list\n");
        code.append("     */\n");
        code.append("    List<").append(className).append("> select").append(className).append("List(").append(className).append(" ").append(lowerClassName).append(");\n\n");
        
        code.append("    /**\n");
        code.append("     * Query ").append(className).append(" details\n");
        code.append("     */\n");
        code.append("    ").append(className).append(" select").append(className).append("ById(Long id);\n\n");
        
        code.append("    /**\n");
        code.append("     * Add ").append(className).append("\n");
        code.append("     */\n");
        code.append("    int insert").append(className).append("(").append(className).append(" ").append(lowerClassName).append(");\n\n");
        
        code.append("    /**\n");
        code.append("     * Update ").append(className).append("\n");
        code.append("     */\n");
        code.append("    int update").append(className).append("(").append(className).append(" ").append(lowerClassName).append(");\n\n");
        
        code.append("    /**\n");
        code.append("     * Delete ").append(className).append("\n");
        code.append("     */\n");
        code.append("    int delete").append(className).append("ById(Long id);\n\n");
    }
    
    // 生成Service方法实现
    private void generateServiceMethodImplementations(StringBuilder code) {
        code.append("    @Override\n");
        code.append("    public List<").append(className).append("> select").append(className).append("List(").append(className).append(" ").append(lowerClassName).append(") {\n");
        code.append("        return ").append(lowerClassName).append("Mapper.select").append(className).append("List(").append(lowerClassName).append(");\n");
        code.append("    }\n\n");
        
        code.append("    @Override\n");
        code.append("    public ").append(className).append(" select").append(className).append("ById(Long id) {\n");
        code.append("        return ").append(lowerClassName).append("Mapper.select").append(className).append("ById(id);\n");
        code.append("    }\n\n");
        
        code.append("    @Override\n");
        code.append("    public int insert").append(className).append("(").append(className).append(" ").append(lowerClassName).append(") {\n");
        code.append("        return ").append(lowerClassName).append("Mapper.insert").append(className).append("(").append(lowerClassName).append(");\n");
        code.append("    }\n\n");
        
        code.append("    @Override\n");
        code.append("    public int update").append(className).append("(").append(className).append(" ").append(lowerClassName).append(") {\n");
        code.append("        return ").append(lowerClassName).append("Mapper.update").append(className).append("(").append(lowerClassName).append(");\n");
        code.append("    }\n\n");
        
        code.append("    @Override\n");
        code.append("    public int delete").append(className).append("ById(Long id) {\n");
        code.append("        return ").append(lowerClassName).append("Mapper.delete").append(className).append("ById(id);\n");
        code.append("    }\n\n");
    }
    
    // 生成Controller方法
    private void generateControllerMethods(StringBuilder code) {
        if (useSwagger) {
            code.append("    @ApiOperation(\"Get ").append(className).append(" list\")\n");
        }
        code.append("    @GetMapping(\"/list\")\n");
        code.append("    public ResponseEntity<List<").append(className).append(">> list(").append(className).append(" ").append(lowerClassName).append(") {\n");
        code.append("        List<").append(className).append("> list = ").append(lowerClassName).append("Service.select").append(className).append("List(").append(lowerClassName).append(");\n");
        code.append("        return ResponseEntity.ok(list);\n");
        code.append("    }\n\n");
        
        if (useSwagger) {
            code.append("    @ApiOperation(\"Get ").append(className).append(" details\")\n");
        }
        code.append("    @GetMapping(\"/{id}\")\n");
        code.append("    public ResponseEntity<").append(className).append("> getInfo(@PathVariable(\"id\") Long id) {\n");
        code.append("        ").append(className).append(" ").append(lowerClassName).append(" = ").append(lowerClassName).append("Service.select").append(className).append("ById(id);\n");
        code.append("        return ResponseEntity.ok(").append(lowerClassName).append(");\n");
        code.append("    }\n\n");
        
        if (useSwagger) {
            code.append("    @ApiOperation(\"Add ").append(className).append("\")\n");
        }
        code.append("    @PostMapping\n");
        code.append("    public ResponseEntity<Integer> add(@RequestBody ").append(className).append(" ").append(lowerClassName).append(") {\n");
        code.append("        int rows = ").append(lowerClassName).append("Service.insert").append(className).append("(").append(lowerClassName).append(");\n");
        code.append("        return ResponseEntity.ok(rows);\n");
        code.append("    }\n\n");
        
        if (useSwagger) {
            code.append("    @ApiOperation(\"Update ").append(className).append("\")\n");
        }
        code.append("    @PutMapping\n");
        code.append("    public ResponseEntity<Integer> edit(@RequestBody ").append(className).append(" ").append(lowerClassName).append(") {\n");
        code.append("        int rows = ").append(lowerClassName).append("Service.update").append(className).append("(").append(lowerClassName).append(");\n");
        code.append("        return ResponseEntity.ok(rows);\n");
        code.append("    }\n\n");
        
        if (useSwagger) {
            code.append("    @ApiOperation(\"Delete ").append(className).append("\")\n");
        }
        code.append("    @DeleteMapping(\"/{id}\")\n");
        code.append("    public ResponseEntity<Integer> remove(@PathVariable Long id) {\n");
        code.append("        int rows = ").append(lowerClassName).append("Service.delete").append(className).append("ById(id);\n");
        code.append("        return ResponseEntity.ok(rows);\n");
        code.append("    }\n\n");
    }
    
    // 生成基本SQL语句
    private void generateBasicSqlStatements(StringBuilder code) {
        // 查询列表
        code.append("    <select id=\"select").append(className).append("List\" resultMap=\"BaseResultMap\">\n");
        code.append("        SELECT * FROM ").append(tableName).append("\n");
        code.append("        <where>\n");
        for (Map<String, String> attr : attributes) {
            String name = attr.get("name");
            String column = toUnderScoreCase(name);
            code.append("            <if test=\"").append(name).append(" != null\">\n");
            code.append("                AND ").append(column).append(" = #{").append(name).append("}\n");
            code.append("            </if>\n");
        }
        code.append("        </where>\n");
        code.append("    </select>\n\n");
        
        // 查询详情
        code.append("    <select id=\"select").append(className).append("ById\" resultMap=\"BaseResultMap\">\n");
        code.append("        SELECT * FROM ").append(tableName).append(" WHERE id = #{id}\n");
        code.append("    </select>\n\n");
        
        // 插入
        code.append("    <insert id=\"insert").append(className).append("\" parameterType=\"").append(basePackage).append(".entity.").append(className).append("\">\n");
        code.append("        INSERT INTO ").append(tableName).append(" (\n");
        
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();
        
        for (Map<String, String> attr : attributes) {
            String name = attr.get("name");
            String column = toUnderScoreCase(name);
            
            if (columns.length() > 0) {
                columns.append(", ");
                values.append(", ");
            }
            
            columns.append(column);
            values.append("#{").append(name).append("}");
        }
        
        code.append("            ").append(columns.toString()).append("\n");
        code.append("        ) VALUES (\n");
        code.append("            ").append(values.toString()).append("\n");
        code.append("        )\n");
        code.append("    </insert>\n\n");
        
        // 更新
        code.append("    <update id=\"update").append(className).append("\" parameterType=\"").append(basePackage).append(".entity.").append(className).append("\">\n");
        code.append("        UPDATE ").append(tableName).append("\n");
        code.append("        <set>\n");
        
        for (Map<String, String> attr : attributes) {
            String name = attr.get("name");
            if (!"id".equals(name)) {  // 不更新ID
                String column = toUnderScoreCase(name);
                code.append("            <if test=\"").append(name).append(" != null\">\n");
                code.append("                ").append(column).append(" = #{").append(name).append("},\n");
                code.append("            </if>\n");
            }
        }
        
        code.append("        </set>\n");
        code.append("        WHERE id = #{id}\n");
        code.append("    </update>\n\n");
        
        // 删除
        code.append("    <delete id=\"delete").append(className).append("ById\" parameterType=\"Long\">\n");
        code.append("        DELETE FROM ").append(tableName).append(" WHERE id = #{id}\n");
        code.append("    </delete>\n\n");
    }
    
    // 生成Getter/Setter方法
    private void generateGettersSetters(StringBuilder code) {
        for (Map<String, String> attr : attributes) {
            String name = attr.get("name");
            String type = attr.get("type");
            String capName = name.substring(0, 1).toUpperCase() + name.substring(1);
            
            // Getter
            code.append("    public ").append(type).append(" get").append(capName).append("() {\n");
            code.append("        return ").append(name).append(";\n");
            code.append("    }\n\n");
            
            // Setter
            code.append("    public void set").append(capName).append("(").append(type).append(" ").append(name).append(") {\n");
            code.append("        this.").append(name).append(" = ").append(name).append(";\n");
            code.append("    }\n\n");
        }
    }
    
    // 驼峰转下划线
    private String toUnderScoreCase(String camelCase) {
        StringBuilder result = new StringBuilder();
        if (camelCase != null && camelCase.length() > 0) {
            result.append(camelCase.charAt(0));
            for (int i = 1; i < camelCase.length(); i++) {
                char c = camelCase.charAt(i);
                if (Character.isUpperCase(c)) {
                    result.append("_");
                    result.append(Character.toLowerCase(c));
                } else {
                    result.append(c);
                }
            }
        }
        return result.toString();
    }
}